package top.i89ck.modules.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.jfinal.aop.Inject;
import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.SqlPara;
import top.i89ck.modules.model.Option;
import top.i89ck.modules.model.Role;
import top.i89ck.modules.model.RoleOption;
import top.i89ck.modules.model.User;
import top.i89ck.modules.utils.Pager;
import top.i89ck.modules.utils.Subject;

import java.sql.SQLException;
import java.util.*;

/**
 * 角色相关的服务
 *
 * @author liyingfu
 */
public class RoleService {

    @Inject
    private OptionService optService;

    /**
     * 角色的列表数据查询， 用于提供角色的具体查询信息
     *
     * @param roleName 角色名称
     * @param pager    当前第几页
     * @return
     */
    public Page<Role> getPage(Pager pager, String roleName) {
        SqlPara sqlPara = Db.getSqlPara("sysRole.getAll", Kv.by("roleName", roleName));
        Page<Role> page = Role.dao.paginate(pager.getPageNum(), pager.getPageSize(), sqlPara);
        return page;
    }

    /**
     * 批量删除系统中的角色数据信息
     *
     * @param roleIds
     * @return
     */
    public boolean delAll(List<String> roleIds, User sessionUser) {
        Kv data = Kv.by("roleIds", roleIds).set("delTime", DateUtil.date()).set("delLoginName", sessionUser.getLoginName());
        SqlPara sqlPara = Db.getSqlPara("sysRole.delAll", data);
        int rows = Db.update(sqlPara);
        return rows > 0;
    }

    /**
     * 更新用户的角色-权限关联信息表。 实现角色与权限的关联操作
     *
     * @param roleId
     * @param optionIds
     * @return
     */
    public boolean saveRoleOptions(Long roleId, List<String> optionIds) {
        List<RoleOption> list = new ArrayList<>();
        for (String optionId : optionIds) {
            RoleOption ro = new RoleOption();
            ro.setRoleId(roleId);
            ro.setOptionId(NumberUtil.parseLong(optionId));
            list.add(ro);
        }
        return Db.tx(() -> {
            clearByRoleId(roleId);
            int[] rows = Db.batchSave(list, list.size());
            return rows.length == list.size();
        });
    }

    /**
     * 通过角色主键清除角色与权限关联关系
     *
     * @param roleId
     * @return
     */
    protected void clearByRoleId(Long roleId) {
        Kv data = Kv.by("roleId", roleId);
        SqlPara sqlPara = Db.getSqlPara("sysRoleOption.clearByRoleId", data);
        Db.update(sqlPara);
    }

    /**
     * 通过角色主键查询角色权限关联的所有的角色的信息
     *
     * @param roleId
     * @return
     * @author YINGFU 2019年4月11日
     */
    public List<Map<String, Object>> getZtreeOptionsByRoleId(Long roleId) {
        List<Option> options = optService.getTreeAll();
        List<RoleOption> ropts = getListByRoleId(roleId);
        // 转成ztree的数据
        List<Map<String, Object>> list = new ArrayList<>();
        setZtreeList(options, list, ropts);
        return list;
    }

    /**
     * 通过觉得色主键获取角色对应的权限列表
     *
     * @param roleId
     * @return
     */
    private List<RoleOption> getListByRoleId(Long roleId) {
        Kv data = Kv.by("roleId", roleId);
        SqlPara sqlPara = Db.getSqlPara("sysRoleOption.getListByRoleId", data);
        return RoleOption.dao.find(sqlPara);
    }

    /**
     * 重置数据， 使数据成为ztree适合的数据模型
     *
     * @param options
     * @param roots
     * @param ropts
     * @author YINGFU 2019年4月11日
     */
    @SuppressWarnings("unchecked")
    private void setZtreeList(Collection<Option> options, List<Map<String, Object>> roots, List<RoleOption> ropts) {
        int i = 0;
        for (Option option : options) {
            Map<String, Object> root = new HashMap<>(6);
            root.put("id", option.getId());
            root.put("name", option.getLabel());
            root.put("pId", option.getParentId());
            for (RoleOption ropt : ropts) {
                if (option.getId().equals(ropt.getOptionId())) {
                    root.put("checked", true);
                }
            }
            root.put("open", i == 0);
            if (CollUtil.isNotEmpty(option.getChildren())) {
                List<Map<String, Object>> children = new ArrayList<>();
                root.put("children", children);
                setZtreeList(option.getChildren(), (List<Map<String, Object>>) root.get("children"), ropts);
            }
            roots.add(root);
            i++;
        }
    }

    /**
     * 查询系统中所有的角色信息数据
     *
     * @return
     * @author YINGFU 2019年4月15日
     */
    public List<Role> getAll() {
        SqlPara sqlPara = Db.getSqlPara("sysRole.getAll");
        return Role.dao.find(sqlPara);
    }

    /**
     * 通过角色的主键获取角色信息
     *
     * @param roleId
     * @return
     */
    public Role findById(Long roleId) {
        return Role.dao.findById(roleId);
    }

    /**
     * 新增/修改角色的信息
     *
     * @param role
     * @return
     */
    public boolean save(Role role) {
        User sessionUser = Subject.getSessionUser();
        if (Objects.isNull(role.getId())) {
            role.setCreatedTime(DateUtil.date());
            role.setCreatedBy(sessionUser.getLoginName());
            role.setDeleted(false);
            return role.save();
        } else {
            Role entity = findById(role.getId());
            if (null == entity) {
                role.setCreatedTime(DateUtil.date());
                role.setCreatedBy(sessionUser.getLoginName());
                role.setDeleted(false);
                return role.save();
            } else {
                role.setUpdatedTime(DateUtil.date());
                role.setUpdatedBy(sessionUser.getLoginName());
                return role.update();
            }
        }
    }

}
